#include <8052.h>
#include "I2C.h"
#include "misc.h"
#include "UART.h"

/********************************************************
* Function              : I2C_Delay
* Description           : I2C的延时函数，根据生成的ASM代码，在时钟频率为11.0592MHz下，加上调用代码，该方法延时4.4微秒
    1s(秒)=1000ms(毫秒)=1000000µs(微秒)=1000000000ns(纳秒)
* Parameter             : void
* Return                : void
**********************************************************/
void I2C_Delay() //@11.0592MHz //5-0.659722222222 us
{
    // int i = 0;
    // i++;
}
/********************************************************
* Function              : I2C_Delay_1ms
* Description           : 1ms延时
* Parameter             : void
* Return                : void
**********************************************************/
void I2C_Delay_1ms(void) //误差 -0.651041666667us
{
    unsigned char a, b;
    for (b = 4; b > 0; b--)
        for (a = 113; a > 0; a--)
            ;
}

/********************************************************
* Function              : I2C_Delay_10ms
* Description           : EEPROM中tWR的时间官方时间定义为10ms
    此处不能太小，容易读不出来
* Parameter             : void
* Return                : void
**********************************************************/
void I2C_Delay_10ms() //@11.0592MHz //误差 -0.000000000002us
{
    unsigned char a, b;
    for (b = 151; b > 0; b--)
        for (a = 29; a > 0; a--)
            ;
}

/********************************************************
* Function              : I2C_Stop
* Description           : I2C的初始化
* Parameter             : void
* Return                : void
**********************************************************/
void I2C_Init()
{
    I2C_SDA = 1;
    I2C_SCL = 1;
    I2C_Delay();
    I2C_Delay_1ms();
}

/********************************************************
* Function              : I2C_Stop
* Description           : I2C会话的开始
* Parameter             : void
* Return                : void
**********************************************************/
void I2C_Start()
{
    I2C_SDA = 1;
    I2C_Delay();
    I2C_SCL = 1;
    I2C_Delay();
    I2C_SDA = 0;
    I2C_Delay();
}

/********************************************************
* Function              : I2C_Stop
* Description           : I2C会话的结束
* Parameter             : void
* Return                : void
**********************************************************/
void I2C_Stop()
{
    I2C_SDA = 0;
    I2C_Delay();
    I2C_SCL = 1;
    I2C_Delay();
    I2C_SDA = 1;
    I2C_Delay();
    I2C_Delay_1ms();
}

/********************************************************
* Function              : I2C_Wait_ACK
* Description           : 等待当前I2C设备的ACK信息
* Parameter             : void
* Return                : 返回>0代表正常接收，否则是超时返回
**********************************************************/
unsigned char I2C_Wait_ACK()
{

    char i = 200;
    I2C_SCL = 1;
    while (I2C_SDA == 1 && i--)
    {
        /* code */
    }
    I2C_SCL = 0;
    I2C_Delay();
    return i;
}

/********************************************************
* Function              : I2C_Send_ACK
* Description           : 向当前I2C设备发送ack
* Parameter             : void
* Return                : void
**********************************************************/
void I2C_Send_ACK()
{
    I2C_SCL = 0;
    I2C_Delay();
    I2C_SDA = 0;
    I2C_Delay();
    I2C_SCL = 1;
    I2C_Delay();
    I2C_SCL = 0;
    I2C_Delay();
    I2C_SDA = 1;
    I2C_Delay();
}

/********************************************************
* Function              : I2C_Read_Byte
* Description           : 向I2C中写一个字节
* Parameter             : 
*   @data               : 写的数据
* Return                : void
**********************************************************/
void I2C_Send_Byte(unsigned char data)
{
    unsigned char temp = data;
    //拉低电平，准备干事
    I2C_SCL = 0;
    I2C_Delay();
    for (char i = 0; i < 8; i++)
    {
        //左移时最低位补0，最高位移入PSW的CY位
        temp = temp << 1;
        I2C_SDA = CY;
        //I2C_SCL高电平时传数据
        I2C_Delay();
        I2C_SCL = 1;
        I2C_Delay();
        //还原I2C_SCL为低电平
        I2C_SCL = 0;
        I2C_Delay();
    }
}

/********************************************************
* Function              : I2C_Read_Byte
* Description           : 从I2C中读一个字节
* Parameter             : void
* Return                : 读出的数据
**********************************************************/
unsigned char I2C_Read_Byte()
{
    unsigned char data = 0;

    for (char i = 0; i < 8; i++)
    {
        //拉高I2C_SCL读取数据
        I2C_SCL = 1;
        I2C_Delay();
        data = (data << 1) | I2C_SDA;
        //还原I2C_SCL为低电平
        I2C_SCL = 0;
        I2C_Delay();
    }
    return data;
}

/********************************************************
* Function              : I2C_Send_To_Address
* Description           : 向I2C设备写入一个字节数据
* Parameter             :
*   @i2c_device_address : I2C设备地址
*   @reg_address        : 寄存器/需求访问的 地址    
*   @reg_data           : 写入的值
* Return                : void
**********************************************************/
void I2C_Send_To_Address(unsigned char i2c_device_address, unsigned char reg_address, unsigned char reg_data)
{
    I2C_Start();                                    //起始信号
    I2C_Send_Byte(i2c_device_address & 0b11111110); //发送特定的I2C设备地址+写信号（末位为0）
    I2C_Wait_ACK();
    I2C_Send_Byte(reg_address); //内部寄存器地址，
    I2C_Wait_ACK();

    I2C_Send_Byte(reg_data); //内部寄存器数据，
    I2C_Stop();              //发送停止信号
}

/********************************************************
* Function              : I2C_Read_From_Address
* Description           : 从I2C设备读取一个字节数据（8位）
* Parameter             :
*  @i2c_device_address  : I2C设备地址
*  @reg_address         : 寄存器/需求访问的 地址    
* Return                : 寄存器中的值
**********************************************************/
unsigned char I2C_Read_From_Address(unsigned char i2c_device_address, unsigned char reg_address)
{
    unsigned char REG_data;
    I2C_Start();                                    //起始信号
    I2C_Send_Byte(i2c_device_address & 0b11111110); //发送设备地址+写信号
    I2C_Wait_ACK();
    I2C_Send_Byte(reg_address); //发送存储单元地址，从0开始
    I2C_Wait_ACK();

    I2C_Start();
    I2C_Send_Byte(i2c_device_address | 0b1); //发送设备地址+读信号
    I2C_Wait_ACK();
    REG_data = I2C_Read_Byte(); //读出寄存器数据
    I2C_Send_ACK();             //接收应答信号

    I2C_Stop(); //停止信号
    return REG_data;
}